package com.fourfaith.iot.beidou.utils;

import cn.hutool.core.util.HexUtil;
import com.fourfaith.common.utils.AlgorithmUtils;
import com.fourfaith.iot.beidou.enums.FkxxEnum;
import com.fourfaith.iot.beidou.message.inbound.BDfkiMessage;
import com.fourfaith.iot.beidou.pojo.bean.FkxxBean;
import com.fourfaith.iot.device.cloud.access.dubbo.pojo.param.BeiDouParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;


/**
 * @Name AlarmLogParseUtil
 * @Description 0211
 * @Author shiyunan
 * @Create 2022/3/1 11:40
 */
@Slf4j
public class MessageParseUtil {

    private static final String TXSQ_KEY = "$TXSQ";

    private static final String TXXX_KEY = "$TXXX";

    private static final String FKXX_KEY = "$FKXX";

    private static final String ZJXX_KEY = "$ZJXX";

    public static CountDownLatch SEND_LOCK = new CountDownLatch(1);

    public static volatile FkxxBean SEND_RESULT;

    /**
     * 发送前加锁
     */
    public static void preSend() {
        log.info("发送前初始化并加锁");
        SEND_RESULT = null;
        SEND_LOCK = new CountDownLatch(1);
    }

    /**
     * 设置发送结果并解锁
     * @param bDfkiMessage
     */
    public static void setSendResult(BDfkiMessage bDfkiMessage){
        log.info("收到消息发送报文反馈结果：{}", bDfkiMessage);
        SEND_RESULT = new FkxxBean();
        if(bDfkiMessage.getResult().equals("Y")){
            SEND_RESULT.setSuccess(true);
            SEND_RESULT.setErrorMessage("ok");
            SEND_RESULT.setDelayTime(0);
        }else{
            SEND_RESULT.setSuccess(false);
            SEND_RESULT.setErrorMessage(bDfkiMessage.getFailureReason());
            SEND_RESULT.setDelayTime(Integer.valueOf(bDfkiMessage.getTimeRemaining()));
        }
        SEND_LOCK.countDown();
        log.info("解锁,发送结果：{}", SEND_RESULT);
    }


    public static BeiDouParam parse(byte[] messageByte) {
        if (messageByte == null || messageByte.length < 7) {
            log.error("非北斗报文");
            return null;
        }
        String startStr = new String(ArrayUtils.subarray(messageByte, 0, 5));
        log.info("北斗响应：{}", startStr);
        BeiDouParam beiDouParam = null;
        switch (startStr) {
            case FKXX_KEY:
                SEND_RESULT = new FkxxBean();
                SEND_RESULT.setDelayTime(0);
                SEND_RESULT.setSuccess(true);
                SEND_RESULT.setClosed(false);
                SEND_RESULT.setErrorMessage("ok");
                byte[] feedback = ArrayUtils.subarray(messageByte, 10, 11);
                String successHex = HexUtil.encodeHexStr(feedback);
                int successInt = HexUtil.hexToInt(successHex);
                if ("00".equals(successHex)) {
                    SEND_RESULT.setSuccess(true);
                } else if ("04".equals(successHex)) {
                    byte[] delayBytes = ArrayUtils.subarray(messageByte, 11, 15);
                    String delayHex = HexUtil.encodeHexStr(delayBytes);
                    long delay = HexUtil.hexToLong(delayHex);
                    SEND_RESULT.setDelayTime(delay);
                    SEND_RESULT.setSuccess(true);
                } else {
                    FkxxEnum fkxxEnum = FkxxEnum.getFkxxEnumByKey(successInt);
                    String errorMessage;
                    if (fkxxEnum == null) {
                        errorMessage = "反馈异常," + successHex;
                    } else {
                        errorMessage = fkxxEnum.getDesc();
                    }
                    SEND_RESULT.setErrorMessage(errorMessage);
                    SEND_RESULT.setSuccess(false);
                }
                log.info("北斗发送反馈：{}", SEND_RESULT);
                SEND_LOCK.countDown();
                break;
            case TXXX_KEY:
                beiDouParam = new BeiDouParam();
                beiDouParam.setFunctionCode(TXXX_KEY);
                String receivedId = AlgorithmUtils.binaryStringToHexString(ArrayUtils.subarray(messageByte, 7, 10));
                beiDouParam.setReceivedId(receivedId);
                String sendId = AlgorithmUtils.binaryStringToHexString(ArrayUtils.subarray(messageByte, 11, 14));
                beiDouParam.setSendId(sendId);
                String messageContext = AlgorithmUtils.binaryStringToHexString(ArrayUtils.subarray(messageByte, 19, messageByte.length - 2));
                beiDouParam.setMessageContext(messageContext);
                break;
            case ZJXX_KEY:
                beiDouParam = new BeiDouParam();
                beiDouParam.setFunctionCode(ZJXX_KEY);
                int readIndex = 5;
                // 数据长度
                byte[] lengthBytes = new byte[2];
                // src：源数组对象,srcPos：源数组的起始位置,dest：目标数组对象,destPos：目标数组的起始位置,length：要复制的元素个数
                System.arraycopy(messageByte, readIndex, lengthBytes, 0, lengthBytes.length);
                log.info("数据长度：{}", HexUtil.encodeHexStr(lengthBytes));
                readIndex += 2;

                // 北斗卡号
                byte[] beidouIdBytes = new byte[3];
                System.arraycopy(messageByte, readIndex, beidouIdBytes, 0, beidouIdBytes.length);
                String beidouId = HexUtil.encodeHexStr(beidouIdBytes);
                log.info("北斗卡号：{}", beidouId);
                readIndex += 3;
                beiDouParam.setSendId(beidouId);

                // IC卡状态
                byte[] icStatusBytes = new byte[1];
                System.arraycopy(messageByte, readIndex, icStatusBytes, 0, icStatusBytes.length);
                String icStatus = HexUtil.encodeHexStr(icStatusBytes);
                log.info("IC卡状态：{}", icStatus);
                readIndex += 1;
                beiDouParam.setIcStatus(icStatus);

                // 硬件状态
                byte[] hardwareStatusBytes = new byte[1];
                System.arraycopy(messageByte, readIndex, hardwareStatusBytes, 0, hardwareStatusBytes.length);
                String hardwareStatus = HexUtil.encodeHexStr(hardwareStatusBytes);
                log.info("硬件状态：{}", hardwareStatus);
                readIndex += 1;
                beiDouParam.setHardwareStatus(hardwareStatus);

                // 电池电量
                byte[] batteryLevelBytes = new byte[1];
                System.arraycopy(messageByte, readIndex, batteryLevelBytes, 0, batteryLevelBytes.length);
                String batteryLevel = HexUtil.encodeHexStr(batteryLevelBytes);
                log.info("电池电量：{}", batteryLevel);
                readIndex += 1;
                beiDouParam.setBatteryLevel(batteryLevel);

                // 入站状态
                byte[] inboundStatusBytes = new byte[1];
                System.arraycopy(messageByte, readIndex, inboundStatusBytes, 0, inboundStatusBytes.length);
                String inboundStatus = HexUtil.encodeHexStr(inboundStatusBytes);
                log.info("入站状态：{}", inboundStatus);
                readIndex += 1;
                beiDouParam.setInboundStatus(inboundStatus);

                // 功率状况
                List<String> powerConditionList = new ArrayList<>();
                for (int i = 0; i < 6; i++) {
                    byte[] powerConditionBytes = new byte[1];
                    System.arraycopy(messageByte, readIndex, powerConditionBytes, 0, powerConditionBytes.length);
                    String powerCondition = HexUtil.encodeHexStr(powerConditionBytes);
                    log.info("波束{}功率：{}", i + 1, powerCondition);
                    readIndex += 1;
                    powerConditionList.add(powerCondition);
                }
                beiDouParam.setPowerConditionList(powerConditionList);

                break;
            default:
                break;
        }
        return beiDouParam;
    }

    public static byte[] encode(BeiDouParam beiDouParam) {
        byte[] sendIdBytes = HexUtil.decodeHex(beiDouParam.getSendId());
        byte[] receivedIdBytes = HexUtil.decodeHex(beiDouParam.getReceivedId());
        byte[] messageContextBytes = HexUtil.decodeHex(beiDouParam.getMessageContext());

        int iAllLen = 19 + messageContextBytes.length;

        byte[] byMesHeader = {(byte) (0x24), (byte) (0x54), (byte) (0x58), (byte) (0x53), (byte) (0x51)};
        byte[] byAllLen = BaseCommonFunc.int2Bytes(iAllLen);
//        byte[] bySendId = sendIdBytes;
        byte byMesType = (byte) (0x46);
//        byte[] byReceivedId = receivedIdBytes;
        byte[] byMesLen = BaseCommonFunc.int2Bytes((messageContextBytes.length + 1) * 8);
        byte byAckFlag = (byte) (0x01);
        byte[] byMessageContext = new byte[1 + messageContextBytes.length];

        byMessageContext[0] = (byte) (0xA4);
        System.arraycopy(messageContextBytes, 0, byMessageContext, 1, messageContextBytes.length);
//		System.arraycopy(byiCrc16, 0, byMessageContext, 1 + abyRealMsg.length, byiCrc16.length);

        byte[] byAllTemp = new byte[byMesHeader.length + byAllLen.length + sendIdBytes.length + 1 + receivedIdBytes.length + byMesLen.length + 1 + byMessageContext.length];

        System.arraycopy(byMesHeader, 0, byAllTemp, 0, byMesHeader.length);

        System.arraycopy(byAllLen, 0, byAllTemp, byMesHeader.length, byAllLen.length);

        System.arraycopy(sendIdBytes, 0, byAllTemp, byMesHeader.length + byAllLen.length, sendIdBytes.length);

        // System.arraycopy(byMesType, 0, byALLtemp, byMesHeader.length +
        // byAllLen.length + sendIdBytes.length , 1);
        byAllTemp[byMesHeader.length + byAllLen.length + sendIdBytes.length] = byMesType;

        System.arraycopy(receivedIdBytes, 0, byAllTemp, byMesHeader.length + byAllLen.length + sendIdBytes.length + 1, receivedIdBytes.length);

        System.arraycopy(byMesLen, 0, byAllTemp, byMesHeader.length + byAllLen.length + sendIdBytes.length + 1 + receivedIdBytes.length, byMesLen.length);

        // System.arraycopy(byAckFlag, 0, byALLtemp,byMesHeader.length +
        // byAllLen.length + sendIdBytes.length + 1 + byReceivedId.length +
        // byMesLen.length , 1);
        byAllTemp[byMesHeader.length + byAllLen.length + sendIdBytes.length + 1 + receivedIdBytes.length + byMesLen.length] = byAckFlag;

        System.arraycopy(byMessageContext, 0, byAllTemp, byMesHeader.length + byAllLen.length + sendIdBytes.length + 1 + receivedIdBytes.length + byMesLen.length + 1, byMessageContext.length);

        byte byExorCheck = BaseCommonFunc.exorCheck(byAllTemp);

        byte[] byAllMessageContext = new byte[iAllLen];

        System.arraycopy(byAllTemp, 0, byAllMessageContext, 0, byAllTemp.length);
        byAllMessageContext[iAllLen - 1] = byExorCheck;

        // 打印发送信息以便查询
        log.info("[ProtocolWriter_Beidou] print send hex message=" + BaseCommonFunc.bytesToHexString(byAllMessageContext) + "   \n");

        return byAllMessageContext;
    }

    public static void main(String[] args) {
        //$ZJXX
        String payloadString = "245A4A585800150660300000000200000100000074";
        //$FKXX
        //24545858580028065F5760050E9D000000A0A4021101000C000000170226000000020100600300B1
//        String payloadString = "24545858580028065F5760050E9D000000A0A4021101000C000000170226000000020100600300B1";
        byte[] ary = AlgorithmUtils.HexString2Bytes(payloadString);
        BeiDouParam beiDouParam = parse(ary);
        System.out.println(beiDouParam);
    }

    public static void testEncode() {
        BeiDouParam beiDouParam = new BeiDouParam();
        beiDouParam.setMessageContext("7E1102002F747365038225DD3800253C534554414C41524D5458543DD1D8BDADC3F1D6DAC7EBD7A2D2E22C362C332C302C313B3E8D7E");
        beiDouParam.setReceivedId("");
    }

    public static void testParse() {
        //$ZJXX
        String payloadString = "245A4A585800150660300000000200000100000074";
        //$FKXX
        //24545858580028065F5760050E9D000000A0A4021101000C000000170226000000020100600300B1
//        String payloadString = "24545858580028065F5760050E9D000000A0A4021101000C000000170226000000020100600300B1";
        byte[] ary = AlgorithmUtils.HexString2Bytes(payloadString);
        BeiDouParam beiDouParam = parse(ary);
        System.out.println(beiDouParam);
    }
}
